package paper.parse;

import java.util.Vector;
import java.util.LinkedList;
import java.util.Iterator;

import paper.token.TT;
import paper.token.Token;

public class HMMatch {
    Vector<HMArrow> outs = new Vector<HMArrow>(2);
    Parse[] cache;
    boolean terminal = false;

    public HMMatch() {
    }
    
    protected void addOut(TT m, TT out, HMMatch next) {
        outs.add(new HMArrow(m, out, next));
    }
    
    protected void addTerminal() {
        terminal = true;
    }

    public void replaceOut(TT toBeReplaced, TT m, TT out, HMMatch next) {
        for (int i = 0; i < outs.size(); i++) {
            if (outs.get(i).match == toBeReplaced) {
                outs.remove(i);
                addOut(m, out, next);
                return;
            }
        }
        System.err.println("Nothing to be replaced");
    }
    
    public Parse parse(TokenInputStream input) {
        Parse p0;
        int currentIndex = input.mark();
        if (cache == null) {
            cache = new Parse[input.length()+1];
        }
        if (cache[currentIndex] != null) {
            return cache[currentIndex];
        }
        if (input.atEnd()) {
            p0 = new Parse(terminal ? 1.0 : 1e-40, TT.EOF, null);
        } else {
            Token current = input.next();
//                System.out.println("Parsing " + current + " " + outs.size() + " options");
            int x = input.mark();
            HMArrow a0 = outs.get(0);
            p0 = a0.buildParse(current);
            p0.add(a0.goTo.parse(input));
            for (int i = 1; i < outs.size(); i++) {
                HMArrow ai = outs.get(i);
                Parse pi = ai.buildParse(current);
                input.reset(x);
                pi.add(ai.goTo.parse(input));
                if (p0.prob < pi.prob) {
                    p0 = pi;
                }
            }
        }
        cache[currentIndex] = p0;
        return p0;
    }

    public String toString() {
        if (cache == null) {
            return "";
        }
        StringBuilder answer = new StringBuilder();
        for (int i = 0; i < cache.length; i++) {
            String x ;
            if (cache[i] == null) {
                x = "";
            } else {
                x = Integer.toString((int)(-100*Math.log10(cache[i].prob)));
            }
            if (x.length() < 5) {
                x = "     ".substring(x.length()) + x;
            }
            answer.append(x);
        }
        return answer.toString();
    }
}

